﻿
//utils

var HEXString = "0123456789ABCDEF";

function getObject(id) {
    return document.getElementById(id);
}

function saturation(value, low, up) {
    if (value < low) value = low;
    if (value > up) value = up;
    return parseInt(value);
}

function rgb(r, g, b) {
    r = parseInt(r);
    g = parseInt(g);
    b = parseInt(b);
    r = saturation(r, 0, 255);
    g = saturation(g, 0, 255);
    b = saturation(b, 0, 255);
    sr = HEXString[parseInt(r / 16)] + HEXString[r % 16];
    sg = HEXString[parseInt(g / 16)] + HEXString[g % 16];
    sb = HEXString[parseInt(b / 16)] + HEXString[b % 16];
    return "#" + sr + sg + sb;
}

function between(test, a, b) {
    if (a > b) {
        var t = a;
        a = b;
        b = t;
    }
    return (a <= test) && (test <= b);
}

function getObjectByClassName(parent, classname) {
    if (parent.className && (parent.className == classname)) return parent;
    if (parent.hasChildNodes()) {
        var n = parent.childNodes.length;
        var i;
        for (i = 0; i < n; i++) {
            var result = getObjectByClassName(parent.childNodes[i], classname);
            if (result) return result;
        }
    }
    return null;
}

function isChild(parent, obj) {
    if (parent == obj) return true;
    if (parent.hasChildNodes()) {
        var n = parent.childNodes.length;
        var i;
        for (i = 0; i < n; i++) {
            if (isChild(parent.childNodes[i], obj)) {
                return true;
            }
        }
    }
    return false;
}

function applyStyle(obj, stylename, value) {
    if (obj.style) {
        obj.style.setProperty(stylename, value);
    }
    if (obj.hasChildNodes()) {
        var n = obj.childNodes.length;
        var i;
        for (i = 0; i < n; i++) {
            applyStyle(obj.childNodes[i], stylename, value);
        }
    }
}

function recoverStyle(obj, stylename) {
    if (obj.style) {
        obj.style.setProperty(stylename, "");
    }
    if (obj.hasChildNodes()) {
        var n = obj.childNodes.length;
        var i;
        for (i = 0; i < n; i++) {
            recoverStyle(obj.childNodes[i], stylename);
        }
    }
}

// open or close elements
function OpenCloseHelper(s_obj, s_max, s_step, s_interval) {
    this.targetObj = s_obj;
    this.maxSize = s_max;
    this.opening = false;
    this.closing = false;
    this.step = s_step;
    this.interval = s_interval;
}
OpenCloseHelper.prototype.openObject = function () {
    this.closing = false;
    if (!this.opening) {
        this.opening = true;
        this._openCallback();
    }
}
OpenCloseHelper.prototype._openCallback = function () {
    var that = this;
    if (!this.opening) return;
    var obj = this.targetObj;
    if (obj.offsetHeight >= obj.maxSize) {
        this.opening = false;
        return;
    }
    var n = parseInt(obj.offsetHeight) + this.step;
    n = Math.min(n, this.maxSize);
    obj.style.height = n + "px";
    setTimeout(function () { that._openCallback(); }, this.interval);
}
OpenCloseHelper.prototype.closeObject = function () {
    this.opening = false;
    if (!this.closing) {
        this.closing = true;
        this._closeCallback();
    }
}
OpenCloseHelper.prototype._closeCallback = function () {
    var that = this;
    if (!this.closing) return;
    var obj = this.targetObj;
    if (obj.offsetHeight <= 0) {
        this.closing = false;
        return;
    }
    var n = parseInt(obj.offsetHeight) - this.step;
    n = Math.max(n, 0);
    obj.style.height = n + "px";
    setTimeout(function () { that._closeCallback(); }, this.interval);
}

// PopupServices
function PopupManager() { }
PopupManager.addListener = function (srcid, destid, s_step, s_interval) {

    var srcobj = getObject(srcid);
    var destobj = getObject(destid);
    destobj.maxHeight = destobj.offsetHeight;
    destobj.style.height = 0;
    srcobj.targetPopObj = destobj;
    destobj._popup = new OpenCloseHelper(destobj, destobj.maxHeight, s_step, s_interval);

    var src_onmouseover = function () {
        if (!this.targetPopObj) return;
        var targetobj = this.targetPopObj;
        targetobj._popup.openObject.call(targetobj._popup);
    }
    srcobj.onmouseover = src_onmouseover;

    var dest_onmouseout = function () {
        if (!isChild(this, event.toElement)) {
            this._popup.closeObject.call(this._popup);
        }
    }
    destobj.onmouseout = dest_onmouseout;
}

// linear change color
function LinearChangeHelper(obj, startcolorarr, endcolorarr, totaltime, segments) { 

    this._startcolor = startcolorarr.slice(0);
    this._endcolor = endcolorarr.slice(0);
    this._deltacolor = new Array(3);
    this._segments = segments;
    var i;
    for (i = 0; i < 3; i++) {
        this._deltacolor[i] = parseFloat(endcolorarr[i] - startcolorarr[i]) / parseFloat(segments);
    }
    this._deltatime = parseFloat(totaltime) / parseFloat(segments);
    this.working = false;
    this.targetobj = obj;
}
LinearChangeHelper.prototype.hide = function () {
    if (this.working) return;
    this.working = true;
    this._curcolor = this._startcolor.slice(0);
    applyStyle(this.targetobj, "color", rgb(this._curcolor[0], this._curcolor[1], this._curcolor[2]));
    this._iter = 0;

    var that = this;
    var _callback = function () {
        that._iter++;
        var i;
        for (i = 0; i < 3; i++) that._curcolor[i] += that._deltacolor[i];
        applyStyle(that.targetobj, "color", rgb(that._curcolor[0], that._curcolor[1], that._curcolor[2]));
        if (that._iter == that._segments) {
            clearInterval(that._clockid);
            that.working = false;
        }
    }
    this._clockid = setInterval(_callback, this._deltatime);
}
LinearChangeHelper.prototype.show = function () {
    if (this.working) return;
    this.working = true;
    this._curcolor = this._endcolor.slice(0);
    applyStyle(this.targetobj, "color", rgb(this._curcolor[0], this._curcolor[1], this._curcolor[2]));
    this._iter = 0;

    var that = this;
    var _callback = function () {
        that._iter++;
        var i;
        for (i = 0; i < 3; i++) that._curcolor[i] -= that._deltacolor[i];
        applyStyle(that.targetobj, "color", rgb(that._curcolor[0], that._curcolor[1], that._curcolor[2]));
        if (that._iter == that._segments) {
            clearInterval(that._clockid);
            that.working = false;
            recoverStyle(that.targetobj, "color");
        }
    }
    this._clockid = setInterval(_callback, this._deltatime);
}

// side links
function SideLinks(xml, target, islast) {
    var title = xml.getAttribute("title");
    var html = "";
    html += "<div class='sidelink'><div class='sidelinkheader'><h2>" + title + "</h2><a href='javascript:'><img src='/images/up.png' /></a></div>";
    html += "<div class='sidelinkcontent'><ul>";
    var i, n = xml.childNodes.length;
    for (i = 0; i < n; i++) {
        var item = xml.childNodes[i];
        var it = item.getAttribute("title"), il = item.getAttribute("url");
        html += "<li><a href='" + il + "'>" + it + "</a></li>";
    }
    html += "</ul></div></div>";
    var frag = document.createElement("tmp");
    frag.innerHTML = html;
    var current = frag.getElementsByTagName("img");
    this.icon = current[0];
    var imglink = current[0].parentNode;
    var that = this;
    imglink.onclick = function () {
        that._firehandler.call(that);
    }
    var node = frag.childNodes[0];
    target.appendChild(node);

    this.targetframe = node;
    //this.working = false;
    this.state = "open";
    this.content = getObjectByClassName(node, "sidelinkcontent");
    this.maxsize = this.content.offsetHeight;
    this._popuphelper = new OpenCloseHelper(this.content, this.content.offsetHeight, 2, 15);
    this.islast = islast;

    var list = this.content.getElementsByTagName("li");
    n = list.length;
    var startcolor = new Array(48, 48, 128);
    var endcolor = new Array(244, 244, 244);
    for (i = 0; i < n; i++) {
        list[i]._fade = new LinearChangeHelper(list[i], startcolor, endcolor, 100, 10);
    }
}

SideLinks.working = false;

SideLinks.prototype._firehandler = function () {
    if (!SideLinks.working) {
        SideLinks.working = true;
        that = this;
        var list = this.content.getElementsByTagName("li");
        var n = list.length;
        var tm = 0, i;
        if (this.state == "open") {
            var fun = function (idx, tick) {
                var t = idx;
                setTimeout(function () { list[t]._fade.hide.call(list[t]._fade); }, tick);
            }
            for (i = n - 1; i >= 0; i--) {
                fun(i, tm);
                tm += 100;
            }
            this.icon.src = "/images/down.png";
            setTimeout(function () { that._popuphelper.closeObject(that._popuphelper); }, tm);
            setTimeout(function () { SideLinks.working = false; that.state = "close"; },
                tm + parseInt(that.maxsize * 15 / 2));
        }
        else if (this.state == "close") {
            if (that.islast) {
                tm = 0;
                that.content.style.height = that.maxsize + "px";
            }
            else {
                that._popuphelper.openObject(that._popuphelper);
                tm = parseInt(that.maxsize * 15 / 2);
            }
            var fun = function (idx, tick) {
                var t = idx;
                setTimeout(function () { list[t]._fade.show.call(list[t]._fade); }, tick);
            }

            for (i = 0; i < n; i++) {
                fun(i, tm);
                tm += 100;
            }
            this.icon.src = "/images/up.png";
            setTimeout(function () { SideLinks.working = false; that.state = "open"; }, tm);
        }
    }
}

function MarqueeHelper(obj, starty, endy, totaltime, segments) {
    this.targetobj = obj;
    this._starty = starty;
    this._endy = endy;
    this.speed = totaltime / segments;
    this.step = (endy - starty) / segments;
}
MarqueeHelper.prototype.start = function () {
    if (this.clockid) return;
    var that = this;
    this._cury = this._starty;
    this.targetobj.style.top = parseInt(this._cury) + "px";
    var fun = function () {
        that._cury += that.step;
        if (between(that._cury, that._starty, that._endy)) {
            that.targetobj.style.top = parseInt(that._cury) + "px";
        }
        else {
            that._cury = that._starty;
            that.targetobj.style.top = parseInt(that._cury) + "px";
        }
    }
    this.clockid = setInterval(fun, parseInt(that.speed));
}
MarqueeHelper.prototype.end = function () {
    if (this.clockid) {
        clearInterval(this.clockid);
        this.clockid = null;
    }
}